package com.itheima.stock.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.itheima.stock.constant.StockConstant;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.entity.SysUser;
import com.itheima.stock.service.UserService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.resp.LoginRespVo;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IdWorker idWorker;
    //根据用户名称查询信息
    @Override
    public SysUser getUserByUserName(String userName) {
        SysUser user = sysUserMapper.findByUserName(userName);
        return user;
    }

    @Override
    public R<LoginRespVo> login(LoginReqVo vo) {
        //判断参数是否合法
        if (vo==null || StringUtils.isBlank(vo.getUsername()) || StringUtils.isBlank(vo.getPassword())){
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //判断输入的验证码是否存在
        if(StringUtils.isBlank(vo.getCode())||StringUtils.isBlank(vo.getSessionId())){
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        //3.根据Rkey从redis中获取缓存的校验码
        String redisCode=(String) redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX + vo.getSessionId());
        //判断redis中保存的验证码与输入的验证码是否相同
        if((StringUtils.isBlank(redisCode))||!redisCode.equalsIgnoreCase(vo.getCode())){
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        //根据用户名查询用户信息
        SysUser user=this.sysUserMapper.findByUserName(vo.getUsername());
        //判断用户是否存在，存在则密码校验比对
        if (user==null || !passwordEncoder.matches(vo.getPassword(),user.getPassword())){
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR.getMessage());
        }
        //响应：组装登录成功数据
        LoginRespVo respVo = new LoginRespVo();
        //属性名称与类型必须相同，否则属性值无法copy
        BeanUtils.copyProperties(user,respVo);
        return  R.ok(respVo);
    }
    //登录校验码实现
    @Override
    public R<Map> getCaptchaCode() {
        //生成图片验证码
        //参数1：图片宽度，参数2：图片高度，参数3：图片中包含验证码的长度，参数4：干扰线数量
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //设置背景颜色清灰
        captcha.setBackground(Color.lightGray);
        //获取校验码
        String code = captcha.getCode();
        //获取经过base64编码处理的图片数据
        String imageData = captcha.getImageBase64();
        //生成sessionid转化为string，避免前端精度丢失
        String sessionId =String.valueOf(idWorker.nextId()) ;
        log.info("当前生成的图片校验码：{}，会话id：{}",code,sessionId);
        //将sessionid作为key，校验码作为value保存在redis，用redis模拟session行为，通过过期时间设置
        redisTemplate.opsForValue().set(StockConstant.CHECK_PREFIX +sessionId,code,5, TimeUnit.MINUTES);
        //组装数据
        Map<String,String> data=new HashMap<>();
        data.put("imageData",imageData);
        data.put("sessionId",sessionId);
        //响应数据
        return R.ok(data);
    }
}
